<template>
  <el-form
    :model="formData"
    :label-width="labelWidth"
    :label-position="labelPosition"
    :style="labelPosition !== 'top' ? formStyle : {}"
    :rules="formRules"
    :class="['form-render', labelPosition === 'top' ? 'form-render-top' : '']"
    ref="formRef"
  >
    <template v-for="field in schema" :key="field.prop">
      <el-form-item :label="field.label" :prop="field.prop">
        <template v-if="field.type === 'inputSelect'">
          <el-input
            v-if="field.type === 'inputSelect'"
            v-model="formData[field.prop]"
            style="max-width: 150px"
            placeholder="请输入"
            class="input-with-select"
          >
          </el-input>
          <el-select
            v-model="formData[field.unit]"
            style="width: 70px; margin-left: 5px"
          >
            <el-option label="天" value="天" />
          </el-select>
        </template>

        <component
          :is="getComponent(field.component)"
          v-model="formData[field.prop]"
          v-if="field.type !== 'inputSelect'"
          v-bind="getComponentProps(field)"
        >
          <!-- 统一的选项渲染 -->
          <template
            v-if="
              field.options && !componentsWithoutChild.includes(field.component)
            "
          >
            <component
              v-for="option in field.options"
              :key="option.value"
              :is="getOptionComponent(field.component)"
              :label="option.label"
              :value="option.value"
            >
              {{ option.label }}
            </component>
          </template>
        </component>
      </el-form-item>
    </template>
  </el-form>
</template>

<script lang="ts" setup name="公共表单组件">
  import { computed } from "vue";
  import {
    ElInput,
    ElSelect,
    ElOption,
    ElDatePicker,
    ElTimePicker,
    ElSwitch,
    ElCheckbox,
    ElCheckboxGroup,
    ElRadio,
    ElRadioGroup,
    ElInputNumber,
    ElCascader,
    ElTreeSelect,
    ElSlider,
    ElRate,
    ElColorPicker,
    ElTransfer,
    ElAutocomplete,
    ElTimeSelect,
    ElUpload,
  } from "element-plus";

  // 类型定义
  interface FormFieldOption {
    label: string;
    value: any;
    disabled?: boolean;
    children?: FormFieldOption[];
  }

  interface FormField {
    component: string;
    prop: string;
    label: string;
    type?: string;
    placeholder?: string;
    disabled?: boolean;
    clearable?: boolean;
    options?: FormFieldOption[];
    rules?: any[];
    [key: string]: any;
  }

  interface Props {
    schema: FormField[];
    modelValue: Record<string, any>;
    labelWidth?: string;
    labelPosition?: string;
    formStyle?: Record<string, any>;
  }

  const props = withDefaults(defineProps<Props>(), {
    labelWidth: "auto",
    labelPosition: "left",
    formStyle: () => ({ maxWidth: "600px" }),
    schema: () => [],
  });

  const emit = defineEmits<{
    "update:modelValue": [value: Record<string, any>];
  }>();

  // 不需要子元素的组件（这些组件有自己的方式处理选项）
  const componentsWithoutChild = [
    "cascader",
    "transfer",
    "input",
    "input-number",
    "date-picker",
    "time-picker",
    "time-select",
    "datetime-picker",
    "switch",
    "slider",
    "rate",
    "color-picker",
    "upload",
  ];

  // 表单验证规则
  const formRules = computed(() => {
    const rules: Record<string, any[]> = {};
    props.schema.forEach((field) => {
      if (field.rules && field.rules.length > 0) {
        rules[field.prop] = field.rules;
      }
    });

    console.log("rules", rules);
    console.log("formData", formData);
    return rules;
  });

  // 表单数据
  const formData = computed({
    get: () => props.modelValue,
    set: (value) => emit("update:modelValue", value),
  });

  // 组件映射
  const componentMap: Record<string, any> = {
    input: ElInput,
    "input-number": ElInputNumber,
    select: ElSelect,
    "tree-select": ElTreeSelect,
    cascader: ElCascader,
    transfer: ElTransfer,
    autocomplete: ElAutocomplete,
    "date-picker": ElDatePicker,
    "time-picker": ElTimePicker,
    "time-select": ElTimeSelect,
    "datetime-picker": ElDatePicker,
    switch: ElSwitch,
    checkbox: ElCheckbox,
    "checkbox-group": ElCheckboxGroup,
    radio: ElRadio,
    "radio-group": ElRadioGroup,
    slider: ElSlider,
    rate: ElRate,
    "color-picker": ElColorPicker,
    upload: ElUpload,
  };

  // 选项组件映射
  const optionComponentMap: Record<string, any> = {
    select: ElOption,
    "tree-select": ElOption,
    autocomplete: ElOption,
    "checkbox-group": ElCheckbox,
    "radio-group": ElRadio,
  };

  // 获取组件
  const getComponent = (component: string) => {
    return componentMap[component] || ElInput;
  };

  // 获取选项组件
  const getOptionComponent = (component: string) => {
    return optionComponentMap[component] || ElOption;
  };

  // 获取组件props
  const getComponentProps = (field: FormField) => {
    const baseProps = {
      ...field, // 这里直接展开剩余的所有属性
      placeholder:
        field.placeholder ||
        getDefaultPlaceholder(field.component, field.label),
    };

    // 特殊组件的props
    const specialProps: Record<string, any> = {};

    // transfer 组件需要通过 data 传递数据
    if (field.component === "transfer" && field.options) {
      specialProps.data = field.options;
    }

    // 日期时间选择器设置宽度
    if (field?.component?.includes("picker")) {
      specialProps.style = { width: "100%" };
    }
    return { ...baseProps, ...specialProps };
  };

  // 获取默认placeholder
  const getDefaultPlaceholder = (component: string, label: string) => {
    if (
      ["select", "tree-select", "cascader", "autocomplete"].includes(component)
    ) {
      return `请选择${label}`;
    }
    return `请输入${label}`;
  };
</script>

<style scoped lang="scss">
  .form-render {
    --el-border-color: #e6e6e6;
    --el-color-primary: #1aa1fb;

    :deep(.el-form-item--label-right .el-form-item__label) {
      text-align: left;
      justify-content: flex-start;
      font-weight: 400;
      font-size: 14px;
      line-height: 24px;
      display: flex;
      align-items: center;
    }

    :deep(.el-date-editor .el-range-separator) {
      color: #999999;
    }
  }

  .form-render-top {
    :deep(.el-form-item--label-top .el-form-item__label) {
      font-weight: 500;
      color: #181818;
    }
  }
</style>
